package com.liveinstars.im.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.liveinstars.api.dto.BatchImGetUserReq;
import com.liveinstars.api.dto.ImGetUserInfo;
import com.liveinstars.api.facade.ImUserCentreApi;
import com.liveinstars.im.common.dto.UserDTO;
import com.liveinstars.im.common.enums.IMExceptionEnum;
import com.liveinstars.im.domain.dao.model.ChatGroup;
import com.liveinstars.im.domain.dao.model.ChatGroupMember;
import com.liveinstars.im.domain.dao.model.Friends;
import com.liveinstars.im.domain.manager.ChatGroupManager;
import com.liveinstars.im.domain.manager.ChatGroupMemberManager;
import com.liveinstars.im.domain.manager.FansManager;
import com.liveinstars.im.domain.manager.FriendsManager;
import com.liveinstars.api.im.query.FriendsQuery;
import com.liveinstars.api.im.vo.ImUserVO;
import com.onepiece.cache.service.CacheService;
import com.liveinstars.im.common.enums.ChatGroupTypeEnum;
import com.liveinstars.im.common.exception.IMRuntimeException;
import com.liveinstars.im.constant.ServerConstant;
import com.liveinstars.im.core.service.UserService;
import com.onepiece.shipelves.common.Result;
import com.onepiece.shipelves.common.enums.SystemExceptionEnum;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: zhouze
 * @date: 2020/4/8
 */
@Service("userService")
public class UserServiceImpl implements UserService {

    private final static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private FriendsManager friendsManager;

    @Autowired
    private FansManager fansManager;

    @Autowired
    private ChatGroupManager chatGroupManager;

    @Autowired
    private ChatGroupMemberManager chatGroupMemberManager;

    @Autowired
    private ImUserCentreApi imUserCentreApi;

    @Autowired
    private CacheService cacheService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createTemporaryFriend(Long applyUserId, Long acceptUserId) {
        friendsManager.saveFriends(applyUserId, acceptUserId, 2);
        ChatGroup friendsChatGroup = chatGroupManager.getFriendsChatGroup(acceptUserId, acceptUserId);
        if (friendsChatGroup == null) {
            createFriendChatGroup(applyUserId, acceptUserId, true);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createFriend(Long applyUserId, Long acceptUserId) {
        friendsManager.saveFriends(applyUserId, acceptUserId, 1);
        createFriendChatGroup(applyUserId, acceptUserId, false);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createFriendChatGroup(Long applyUserId, Long acceptUserId, Boolean isTemporary) {
        ChatGroup friendsChatGroup = chatGroupManager.createFriendsChatGroup(applyUserId, acceptUserId);
        List<ChatGroupMember> list = Lists.newArrayList();
        ChatGroupMember chatGroupMember = new ChatGroupMember();
        chatGroupMember.setUserId(applyUserId);
        chatGroupMember.setGroupType(ChatGroupTypeEnum.PERSON_TO_PERSON.getValue());
        chatGroupMember.setChatGroupId(friendsChatGroup.getId());
        list.add(chatGroupMember);
        chatGroupMember = new ChatGroupMember();
        chatGroupMember.setUserId(acceptUserId);
        chatGroupMember.setGroupType(ChatGroupTypeEnum.PERSON_TO_PERSON.getValue());
        chatGroupMember.setChatGroupId(friendsChatGroup.getId());
        list.add(chatGroupMember);
        if (isTemporary) {
            chatGroupMemberManager.batchSaveMember(list, friendsChatGroup.getId());
        } else {
            chatGroupMemberManager.batchSaveFriendMember(list, friendsChatGroup.getId());
        }
    }

    @Override
    public List<ImUserVO> listTemporaryFriendByUserId(Long userId) {
        List<ImUserVO> list = Lists.newArrayList();
        List<Friends> friendList = friendsManager.listFriendsByUserIdAndType(userId, 2);
        transTo(friendList, list);
        return list;
    }

    private void transTo(List<Friends> source, List<ImUserVO> target) {
        if (CollectionUtils.isNotEmpty(source)) {
            List<Long> userIdList = source.stream().map(friends -> friends.getFriendId()).collect(Collectors.toList());
            BatchImGetUserReq req = new BatchImGetUserReq();
            req.setUids(userIdList);
            Result<List<ImGetUserInfo>> listResult = imUserCentreApi.batchImGetUserInfo(req);
            HashMap<Long, ImGetUserInfo> userIdMap = Maps.newHashMap();
            if (listResult.getCode().equals(Result.SUCCESS)) {
                listResult.getData().stream().forEach(imGetUserInfo -> userIdMap.put(imGetUserInfo.getUid(), imGetUserInfo));
            } else {
                logger.error("获取用户信息失败: params:{}, errorMsg:{}", JSON.toJSONString(req), JSON.toJSONString(listResult));
            }
            source.stream().forEach(friends -> {
                UserDTO userDTO;
                if (userIdMap.containsKey(friends.getFriendId())) {
                    userDTO = new UserDTO(friends, userIdMap.get(friends.getFriendId()));
                } else {
                    userDTO = new UserDTO(friends, new ImGetUserInfo());
                }
                ImUserVO imUserVO = userDTO.friendsTransTo();
                target.add(imUserVO);
            });
        }
    }

    @Override
    public List<ImUserVO> listFriendByUserId(Long userId) {
        List<ImUserVO> list = Lists.newArrayList();
        List<Friends> friendList = friendsManager.listFriendsByUserIdAndType(userId, 1);
        transTo(friendList, list);
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void shieldFriend(Long userId, Long friendUserId) {
        friendsManager.updateShield(userId, friendUserId, true);
        ChatGroup friendsChatGroup = chatGroupManager.getFriendsChatGroup(userId, friendUserId);
        if (friendsChatGroup == null) {
            //TODO 新建通道
        }
        chatGroupMemberManager.updateShield(userId, friendsChatGroup.getId(), true);
    }

    @Override
    public void cancelShieldFriend(Long userId, Long friendUserId) {
        friendsManager.updateShield(userId, friendUserId, false);
        ChatGroup friendsChatGroup = chatGroupManager.getFriendsChatGroup(userId, friendUserId);
        if (friendsChatGroup == null) {
            //TODO 新建通道
        }
        chatGroupMemberManager.updateShield(userId, friendsChatGroup.getId(), false);
    }


    @Override
    public void deleteFriend(Long userId, Long friendUserId) {
        friendsManager.deleteFriends(userId, friendUserId);;
    }

    @Override
    public void remarkFriendName(Long userId, Long friendUserId, String remarkName) {
        FriendsQuery query = new FriendsQuery();
        query.setUserId(userId);
        query.setFriendId(friendUserId);
        Friends friends = new Friends();
        friends.setRemarkName(remarkName);
        friendsManager.updateByQuery(friends, query);
    }

    @Override
    public void shieldUser(Long userId, Long shieldUserId, Boolean shield) {
        ChatGroup friendsChatGroup;
        friendsChatGroup = chatGroupManager.getFriendsChatGroup(userId, shieldUserId);
        if (friendsChatGroup == null) {
            String chatUserKey = "";
            try {
                if (userId > shieldUserId) {
                    chatUserKey = userId + "_" + shieldUserId;
                } else {
                    chatUserKey = shieldUserId + "_" + userId;
                }
                if (cacheService.lock(ServerConstant.CHAT_CHANNEL_CREATE_LOCK + chatUserKey)) {
                    friendsChatGroup = chatGroupManager.getFriendsChatGroup(userId, shieldUserId);
                    if (friendsChatGroup == null) {
                        friendsChatGroup = chatGroupManager.createFriendsChatGroup(userId, shieldUserId);
                        List<ChatGroupMember> memberList = Lists.newArrayList();
                        ChatGroupMember chatGroupMember = new ChatGroupMember();
                        chatGroupMember.setUserId(userId);
                        chatGroupMember.setGroupType(friendsChatGroup.getGroupType());
                        chatGroupMember.setChatGroupId(friendsChatGroup.getId());
                        chatGroupMember.setShield(shield);
                        chatGroupMember.setNoDisturbing(false);
                        chatGroupMember.setShieldTime(Long.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))).intValue());
                        memberList.add(chatGroupMember);
                        chatGroupMember = new ChatGroupMember();
                        chatGroupMember.setUserId(shieldUserId);
                        chatGroupMember.setGroupType(friendsChatGroup.getGroupType());
                        chatGroupMember.setChatGroupId(friendsChatGroup.getId());
                        chatGroupMember.setShield(false);
                        chatGroupMember.setNoDisturbing(false);
                        memberList.add(chatGroupMember);
                        chatGroupMemberManager.batchSaveFriendMember(memberList, friendsChatGroup.getId());
                    } else {
                        chatGroupMemberManager.updateShield(userId, friendsChatGroup.getId(), shield);
                    }
                    cacheService.releaseLock(ServerConstant.CHAT_CHANNEL_CREATE_LOCK + chatUserKey);
                } else {
                    throw new IMRuntimeException(IMExceptionEnum.TODO_DEAL_WITH_IS_REPEAT);
                }
            } catch (Exception e) {
                cacheService.releaseLock(ServerConstant.CHAT_CHANNEL_CREATE_LOCK + chatUserKey);
                if (e instanceof IMRuntimeException) {
                    throw e;
                } else {
                    logger.error("shieldUser error params={} errorMsg:{}",
                            "userId="+userId+" shieldUserId="+shieldUserId,
                            e.getMessage(),
                            e);
                    throw new IMRuntimeException(SystemExceptionEnum.UN_KNOW_ERROR);
                }
            }
        } else {
            chatGroupMemberManager.updateShield(userId, friendsChatGroup.getId(), shield);
        }
    }

    @Override
    public Boolean isShield(Long selfId, Long userId) {
        Boolean result = false;
        ChatGroup friendsChatGroup = chatGroupManager.getFriendsChatGroup(selfId, userId);
        if (friendsChatGroup != null) {
            ChatGroupMember member = chatGroupMemberManager.getChatGroupMemberByGroupIdAndUserId(friendsChatGroup.getId(), selfId);
            result = member.getShield();
        }
        return result;
    }

    @Override
    public ImUserVO getImUserInfo(Long selfId, Long userId) {
        ImUserVO imUserVO = new ImUserVO();
        ChatGroup friendsChatGroup = chatGroupManager.getFriendsChatGroup(selfId, userId);
        if (friendsChatGroup != null) {
            ChatGroupMember member = chatGroupMemberManager.getChatGroupMemberByGroupIdAndUserId(friendsChatGroup.getId(), selfId);
            imUserVO.setShield(member.getShield());
        }
        Friends friends = friendsManager.getFriendsByUserIdAndFriendsId(selfId, userId);
//        //被关注数
//        Integer followedNum = fansManager.countByUserId(userId);
//        //关注数
//        Integer followNum = fansManager.countByFansId(userId);
        if (friends != null) {
            imUserVO.setVisible(friends.getVisible());
            imUserVO.setRemarkName(friends.getRemarkName());
            if (friends.getType().equals(1)) {
                imUserVO.setFriend(true);
            } else {
                imUserVO.setFriend(false);
            }
        } else {
            imUserVO.setFriend(false);
        }
        ImGetUserInfo userInfo = imUserCentreApi.imGetUserInfo(userId);
        imUserVO.setHomePageShow(userInfo.getHomePageShow());
        imUserVO.setUserName(userInfo.getUserName());
        imUserVO.setNickName(userInfo.getNickName());
        imUserVO.setLogo(userInfo.getLogo());
        imUserVO.setIndividualResume(userInfo.getIndividualResume());
        imUserVO.setGroupId(userInfo.getGroupId());
        imUserVO.setRegdate(Long.valueOf(userInfo.getRegdate()));
        imUserVO.setUserId(userInfo.getUid());
//        imUserVO.setFollowNum(followNum);
//        imUserVO.setFollowedNum(followedNum);
        return imUserVO;
    }
}
